/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
 *
 */
import * as path from 'path';

import { CompileModeEnum } from '../../../../src/enum/compile-mode-enum';
import { BuildOptionWithName, ExternalNativeOpt, NapiLibFilterOpt } from '../../../../src/options/build/build-opt';
import { ModuleBuildProfile } from '../../../../src/options/build/module-build-profile';
import { ApiType } from '../../../../src/project/data/hap-extra-info';
import { getElementFromArr } from '../../../../src/utils/array-util';
import { updateElementInArrayByUniqueKey } from '../common';

import { BaseModifier } from './base-modifier';
import BuildModeBinder = ModuleBuildProfile.BuildModeBinder;
import ModuleBuildOpt = ModuleBuildProfile.ModuleBuildOpt;
import ModuleTargetBuildOpt = ModuleBuildProfile.ModuleTargetBuildOpt;

/**
 * 修改指定模块的build-profile.json5
 */
export class ModuleBuildProfileModifier extends BaseModifier {
  protected jsonObject!: ModuleBuildOpt;
  private cwd: string;
  private moduleName: string;

  constructor(cwd: string, moduleName: string) {
    super(path.resolve(cwd, moduleName, 'build-profile.json5'));
    this.cwd = cwd;
    this.moduleName = moduleName;
  }

  /**
   * 仅支持在har中使用修改artifactType
   *
   * @param {string} artifactType
   */
  public setArtifactType(artifactType: string) {
    this.jsonObject.buildOption!.artifactType = artifactType;
    return this;
  }

  public setApiType(apiType: ApiType) {
    this.jsonObject.apiType = apiType;
    return this;
  }

  // buildOption相关方法
  public setBuildOption(option: BuildOptionWithName) {
    this.jsonObject.buildOption = option;
    return this;
  }

  public setBuildOptionSet(option: BuildOptionWithName[]) {
    this.jsonObject.buildOptionSet = option;
    return this;
  }

  public setBuildModeBinder(option: BuildModeBinder[]) {
    this.jsonObject.buildModeBinder = option;
    return this;
  }

  public addBuildModeBinder(buildModeName: string, targetName: string, buildOptionName: string) {
    this.jsonObject.buildModeBinder = this.jsonObject.buildModeBinder ?? [];
    if (!getElementFromArr(this.jsonObject.buildModeBinder, buildModeName, 'buildModeName')) {
      this.jsonObject.buildModeBinder.push({
        buildModeName,
        mappings: [
          {
            targetName,
            buildOptionName
          }
        ]
      });
      return this;
    }
    const buildModeBind = getElementFromArr(this.jsonObject.buildModeBinder, buildModeName, 'buildModeName')!;
    buildModeBind.mappings = buildModeBind.mappings ?? [];
    buildModeBind.mappings.push({
      targetName,
      buildOptionName
    });
    return this;
  }

  public setEntryModules(entryModules: string[]) {
    this.jsonObject.entryModules = entryModules;
    return this;
  }

  public setCompileMode(mode: CompileModeEnum | undefined) {
    this.jsonObject.buildOption = {
      ...this.jsonObject.buildOption,
      compileMode: mode
    };
    return this;
  }

  // Native配置相关方法
  public setNativeOptions(option: ExternalNativeOpt) {
    if (!this.jsonObject.buildOption) {
      this.jsonObject.buildOption = {};
    }
    this.jsonObject.buildOption.externalNativeOptions = option;
    return this;
  }

  public setCppArguments(argument: string) {
    if (this.jsonObject.buildOption?.externalNativeOptions === undefined) {
      this.setNativeOptions({});
    }
    this.jsonObject.buildOption!.externalNativeOptions!.arguments = argument;
    return this;
  }

  public setAbiFilters(abiFilters: string[]) {
    if (this.jsonObject.buildOption?.externalNativeOptions === undefined) {
      this.setNativeOptions({});
    }
    this.jsonObject.buildOption!.externalNativeOptions!.abiFilters = abiFilters;
    return this;
  }

  public setCppFlags(flags: string) {
    if (this.jsonObject.buildOption?.externalNativeOptions === undefined) {
      this.setNativeOptions({});
    }
    this.jsonObject.buildOption!.externalNativeOptions!.cppFlags = flags;
    return this;
  }

  public setCFlags(flags: string) {
    if (this.jsonObject.buildOption?.externalNativeOptions === undefined) {
      this.setNativeOptions({});
    }
    this.jsonObject.buildOption!.externalNativeOptions!.cFlags = flags;
    return this;
  }

  // napiLibFilterOption配置相关方法
  public setNAPIFilterOptions(option: NapiLibFilterOpt, targetName?: string) {
    if (targetName) {
      const target = this.getTarget(targetName);
      this.updateTarget({
        name: 'target',
        ...target,
        config: {
          ...target?.config,
          buildOption: {
            ...target?.config?.buildOption,
            napiLibFilterOption: option
          }
        }
      });
    } else {
      if (!this.jsonObject.buildOption) {
        this.jsonObject.buildOption = {};
      }
      this.jsonObject.buildOption.napiLibFilterOption = option;
    }
    return this;
  }

  public setExcludes(excludes: string[]) {
    if (this.jsonObject.buildOption?.napiLibFilterOption === undefined) {
      this.setNAPIFilterOptions({});
    }
    this.jsonObject.buildOption!.napiLibFilterOption!.excludes = excludes;
    return this;
  }

  public setPickFirsts(pickFirsts: string[]) {
    if (this.jsonObject.buildOption?.napiLibFilterOption === undefined) {
      this.setNAPIFilterOptions({});
    }
    this.jsonObject.buildOption!.napiLibFilterOption!.pickFirsts = pickFirsts;
    return this;
  }

  public setPickLasts(pickLasts: string[]) {
    if (this.jsonObject.buildOption?.napiLibFilterOption === undefined) {
      this.setNAPIFilterOptions({});
    }
    this.jsonObject.buildOption!.napiLibFilterOption!.pickLasts = pickLasts;
    return this;
  }

  public setEnableOverride(override: boolean) {
    if (this.jsonObject.buildOption?.napiLibFilterOption === undefined) {
      this.setNAPIFilterOptions({});
    }
    this.jsonObject.buildOption!.napiLibFilterOption!.enableOverride = override;
    return this;
  }

  // targets配置相关方法
  public getTargets(): ModuleTargetBuildOpt[] | undefined {
    return this.jsonObject.targets;
  }

  public getTarget(targetName: string): ModuleTargetBuildOpt | undefined {
    const targets = this.getTargets();
    if (targets !== undefined) {
      for (const target of targets) {
        if (target.name === targetName) {
          return target;
        }
      }
    }
    return undefined;
  }

  public updateTarget(target: ModuleTargetBuildOpt) {
    updateElementInArrayByUniqueKey(this.jsonObject.targets, target);
    return this;
  }

  public updateTargetRuntimeOS(targetName: string, runtimeOS: string) {
    new ModuleBuildProfileModifier(this.cwd, this.moduleName).updateTarget({
      name: targetName,
      runtimeOS: runtimeOS
    }).outputSync();
  }

  public addTarget(target: ModuleTargetBuildOpt) {
    if (this.jsonObject.targets === undefined) {
      this.jsonObject.targets = [];
    }
    this.jsonObject.targets.push(target);
    return this;
  }

  public removeLastTarget() {
    this.jsonObject.targets?.pop();
    return this;
  }
}
